import { VMFactory } from "./VMFactory";
import { Watcher } from "./Watcher";
import { IVMMain } from "../Interfaces/IMVVM";
import { WatcherComputed } from "./WatcherComputed";

/**
 * 指令解析工具类
 */
export class CompileUtil {
  static $elCurrent: IVMMain; //当前操作元素
  static timer: number;
  public static text(node, vm, exp) {
    this.bind(node, vm, exp, "text");
  }
  //attrName 为执行属性 item
  public static for(node, vm, exp, attrName) {
    this.bind(node, vm, exp, "for", attrName);
  }
  public static display(node, vm, exp) {
    this.bind(node, vm, exp, "display");
  }
  public static class(node, vm, exp) {
    this.bind(node, vm, exp, "class");
  }
  public static attr(node, vm, exp, attrName) {
    this.bind(node, vm, exp, "attr", attrName);
  }
  public static model(node, vm, exp) {
    this.bind(node, vm, exp, "model");

    let self = this;
    let val = this._getVmVal(vm, exp);
    // 监听input事件
    VMFactory.getDirective().addInputListener(node, function (newVal) {
      if (val === newVal) {
        return;
      }
      self._setVmVal(vm, exp, newVal);
      val = newVal;
      CompileUtil.$elCurrent = undefined;
    });
  }
  public static bind(node, vm: IVMMain, exp, dir, attrName?) {
    let updaterFn = VMFactory.getRenderUtil()[dir + "Updater"];
    var computedFn = this.initComputed(vm, exp);
    if (computedFn) {
      new WatcherComputed(vm, exp, node, attrName, function (value, oldValue) {
        updaterFn && updaterFn(node, value, oldValue, attrName, vm);
      }).update();
    } else {
      new Watcher(vm, exp, node, attrName, function (value, oldValue) {
        updaterFn && updaterFn(node, value, oldValue, attrName, vm);
      }).update();
    }
  }
  private static initComputed(vm: IVMMain, exp): any {
    if (vm.$options.computed) {
      return vm.$options.computed[exp];
    } else {
      return null;
    }
  }
  /**事件处理 */
  public static eventHandler(node, vm: IVMMain, exp, dir) {
    let eventType = dir.split(":")[1];
    let fn = vm.$options.methods && vm.$options.methods[exp];
    if (eventType && fn) {
      VMFactory.getDirective().addEventListener(
        node,
        eventType,
        fn.bind(vm),
        0
      );
    }
  }
  /**
   * [获取挂载在vm实例上的value]
   * @param  {[type]} vm  [mvvm实例]
   * @param  {[type]} exp [expression]
   */
  public static _getVmVal(vm, exp) {
    let val = vm;
    exp = exp.split(".");
    exp.forEach((key) => {
      key = key.trim();
      val && (val = val[key]);
    });
    return val;
  }
  /**
   * [设置挂载在vm实例上的value值]
   * @param  {[type]} vm    [mvvm实例]
   * @param  {[type]} exp   [expression]
   * @param  {[type]} value [新值]
   */
  public static _setVmVal(vm, exp, value) {
    let val = vm;
    var exps = exp.split(".");
    exps.forEach((key, index) => {
      key = key.trim();
      if (index < exps.length - 1) {
        val = val[key];
      } else {
        val[key] = value;
      }
    });
  }
}
